﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Com.JunCaiSoft.Common.AssistClass
{
    public class CloneClassAssist
    {
        public static T CloneClass<T>(Object sourceObj, String removeParameters = null) where T : class, new()
        {
            Type type = typeof(T);
            object targetObj = Activator.CreateInstance(type);
            Type targetType = targetObj.GetType();
            Type sourceType = sourceObj.GetType();

            CloneWork(sourceType, targetType, sourceObj, targetObj, removeParameters );

            return (T)targetObj;
        }

        public static T CloneClass<T>(Object sourceObj, Object targetObj, String removeParameters = null) where T : class
        {
            Type type = typeof(T);
            Type targetType = targetObj.GetType();
            Type sourceType = sourceObj.GetType();

            CloneWork(sourceType, targetType, sourceObj, targetObj,removeParameters);

            return (T)targetObj;
        }

        public static void CloneWork(Type sourceType, Type targetType, object sourceObj, object targetObj, String removeParameters = null)
        {
            PropertyInfo[] propertyInfo = sourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance|BindingFlags.SetProperty);

            if(removeParameters != null)
            {
                var removeParametersList = removeParameters.Split(',').ToList();

                var grantValueList = propertyInfo.ToList();
                //去掉用户不允许复制的字段名称集合
                grantValueList.RemoveAll(x => removeParametersList.Contains(x.Name));
                //去掉不允许写的字段集合
                grantValueList.RemoveAll(x => !x.CanWrite);
                //转化为数组
                propertyInfo = grantValueList.ToArray();
            }

            PropertyInfo proertyTargetInfo = null;
            object propertyVal = null;
            foreach (var item in propertyInfo)
            {
                proertyTargetInfo = targetType.GetProperty(item.Name);
                if (proertyTargetInfo == null)
                {
                    Console.WriteLine(item.Name + " 没找到");
                    continue;
                }

                if (proertyTargetInfo.PropertyType.IsClass)
                {
                    if (proertyTargetInfo.PropertyType.Name != "String" && proertyTargetInfo.PropertyType.FullName != "System.String")
                    {
                        if (proertyTargetInfo.GetValue(targetObj) == null)
                        {
                            proertyTargetInfo.SetValue(targetObj, Activator.CreateInstance(proertyTargetInfo.PropertyType));
                        }

                        if(item.GetValue(sourceObj) != null && item.PropertyType.Name != typeof(List<object>).Name 
                            && item.PropertyType.Name != typeof(IEnumerable<object>).Name && item.PropertyType.Name != typeof(Array).Name)
                        {
                            CloneWork(item.GetValue(sourceObj).GetType(), proertyTargetInfo.PropertyType, item.GetValue(sourceObj), proertyTargetInfo.GetValue(targetObj));
                        }
                        //说明是普通的类
                    }
                }

                if (proertyTargetInfo != null && proertyTargetInfo.CanWrite)
                {
                    propertyVal = item.GetValue(sourceObj);
                    if(item.PropertyType.Name == typeof(DateTime).Name && DateTime.Parse(propertyVal.ToString()) == DateTime.MinValue)
                    {
                        propertyVal = DateTime.Now;
                    }
                    proertyTargetInfo.SetValue(targetObj, propertyVal);
                }
            }
        }
    }
}